﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WHControlLib.Controls
{
   
    public partial class WHTrackBar : UserControl
    {
   
      
        public WHTrackBar()
        {//设置双缓冲开启禁止背景擦拭
            SetStyle(
                     ControlStyles.OptimizedDoubleBuffer
                     | ControlStyles.ResizeRedraw
                     | ControlStyles.Selectable
                     | ControlStyles.AllPaintingInWmPaint
                     | ControlStyles.UserPaint
                     | ControlStyles.SupportsTransparentBackColor,
                     true);
            this.BackColor = Color.Transparent;
            InitializeComponent();
        }
        Rectangle MyRect = new Rectangle();
        Rectangle TrackRect=new Rectangle();
        Rectangle TrackValueRect = new Rectangle();
        Rectangle BarRect = new Rectangle();
        //Rectangle ValueMsgRect=new Rectangle();
        Point OldMousePoint = new Point();
        bool IsReady;

        public enum Direction
        {
            horizontal , vertical
        }
        #region 属性定义
        //事件定义
        [Category("A我的事件"), Description("当值改变时候发生"), Browsable(true)]
        public event EventHandler ValueChangeEvent;

        private Color _barBorderColor = Color.DarkBlue;

        /// <summary>
        /// 手柄的边框颜色
        /// </summary>
        [Category("A我的"), Description("手柄的边框颜色，默认深蓝色"), Browsable(true)]
        public Color BarBorderColor
        {
            get { return _barBorderColor; }
            set { _barBorderColor = value; this.Invalidate(); }
        }

        private Color _barFirstFillColor = Color.Orange;
        [Category("A我的"), Description("手柄的内部第一种填充颜色，默认橙色"), Browsable(true)]
        public Color BarFirstFillColor
        {
            get { return _barFirstFillColor; }
            set { _barFirstFillColor = value; this.Invalidate(); }
        }
        private Color _barSecondFillColor = Color.Red;
        [Category("A我的"), Description("手柄的内部第二种填充颜色，默认红色"), Browsable(true)]
        public Color BarSecondFillColor
        {
            get { return _barSecondFillColor; }
            set { _barSecondFillColor = value; this.Invalidate(); }
        }
        private float _barAngleFillColor = 30f  ;
        [Category("A我的"), Description("当手柄的内部用二种填充颜色时候的渐变角度，默认 30.f"), Browsable(true)]
        public float BarAngleFillColor
        {
            get { return _barAngleFillColor; }
            set { _barAngleFillColor = value; this.Invalidate(); }
        }
        private Color _trackBorderColor = Color.Blue;
        /// <summary>
        /// 轨道的边框颜色
        /// </summary>
        [Category("A我的"), Description("轨道的边框颜色，默认蓝色"), Browsable(true)]
        public Color TrackBorderColor
        {
            get { return _trackBorderColor; }
            set { _trackBorderColor = value; this.Invalidate(); }
        }

        private Color _trackFillColor = Color.White;
        [Category("A我的"), Description("轨道的内部颜色，默认白色"), Browsable(true)]
        public Color TrackFillColor
        {
            get { return _trackFillColor; }
            set { _trackFillColor = value; this.Invalidate(); }
        }
        private Color _trackShadowColor = Color.Gray;
        [Category("A我的"), Description("轨道的内部阴影颜色，默认灰色"), Browsable(true)]
        public Color TrackShadowColor
        {
            get { return _trackShadowColor; }
            set { _trackShadowColor = value; this.Invalidate(); }
        }

        private Color _filltrackValueFirstColor =Color.Orange ;
        [Category("A我的"), Description("轨道有值时的第一种内部颜色，默认橙色"), Browsable(true)]
        public Color FilltrackValueFirstColor
        {
            get { return _filltrackValueFirstColor; }
            set { _filltrackValueFirstColor = value; this.Invalidate(); }
        }
        private Color _filltrackValueSecondColor = Color.Red;
        [Category("A我的"), Description("轨道有值时的第二种内部颜色，默认红色"), Browsable(true)]
        public Color FilltrackValueSecondColor
        {
            get { return _filltrackValueSecondColor; }
            set { _filltrackValueSecondColor = value; this.Invalidate(); }
        }

        private float _trackBorderWidth=1.0f;
        [Category("A我的"), Description("轨道外框线宽，默认1.0f"), Browsable(true)]
        public float TrackBorderWidth
        {
            get { return _trackBorderWidth; }
            set { _trackBorderWidth = value; Invalidate(); }
        }

        private float _barBorderWidth =2f;
        [Category("A我的"), Description("手柄的外框线宽，默认2.0f"), Browsable(true)]
        public float BarBorderWidth
        {
            get { return _barBorderWidth; }
            set
            {
                if (value>=this.Height)
                {
                    _barBorderWidth = 1;
                }
                else 
    
                _barBorderWidth = value; Invalidate(); }
        }

        private bool _isShowTrackBorder=true;
        [Category("A我的"), Description("是否显示轨道边框，默认：显示"), Browsable(true)]
        public bool IsShowTranckBorder
        {
            get { return _isShowTrackBorder; }
            set { _isShowTrackBorder = value; Invalidate(); }
        }
        private bool _isShowBarBorder=true;
        [Category("A我的"), Description("是否显示手柄边框，默认：显示"), Browsable(true)]
        public bool IsShowBarBorder
        {
            get { return _isShowBarBorder; }
            set { _isShowBarBorder = value; Invalidate(); }
        }
        private bool _isShowMsg;
        [Category("A我的"), Description("是否显示值的信息框，默认：不显示"), Browsable(true)]
        public bool IsShowMsg
        {
            get { return _isShowMsg; }
            set { _isShowMsg = value; Invalidate(); }
        }
        private bool _isUseTrackShadow=true;
        [Category("A我的"), Description("是否开启轨道内阴影效果，默认：显示"), Browsable(true)]
        public bool IsUseTrackShadow
        {
            get { return _isUseTrackShadow; }
            set { _isUseTrackShadow = value; Invalidate(); }
        }
        private Font _msgFont=new Font("微软雅黑", 10.0f);
        [Category("A我的"), Description("显示值所用的字体，默认：微软雅黑"), Browsable(true)]
        public Font MsgFont 
        {
            get { return _msgFont; }
            set { _msgFont= value; Invalidate(); }
        }

        private Color _msgFontColor = Color.Black;
        [Category("A我的"), Description("显示值所用的字体的颜色，默认：黑色"), Browsable(true)]
        public Color MsgFontColor
        {
            get { return _msgFontColor; }
            set { _msgFontColor = value; Invalidate(); }
        }
        private float _trackHight=4.0f;
        [Category("A我的"), Description("轨道的高度是与控件整体高度的比值，默认：4.0f,不能小于1.5"), Browsable(true)]
           
        public float TrackHight
        {
            get { return _trackHight; }
            set {
                if (value<1.5)
                {
                    _trackHight = 1.5f;

                }
               else  _trackHight= value;
                     Invalidate();
            }
        }

        private float _barHight = 1.5f;
        [Category("A我的"), Description("手柄的高度是与控件整体高度的比值，默认：1.5f 即 1/1.5,不能小于1"), Browsable(true)]

        public float BarHight
        {
            get { return _barHight; }
            set
            {
                if (value < 1)
                {
                    _barHight = 1f;

                }
                else _barHight = value;
                Invalidate();
            }
        }




        private int _maxValue=100;
        [Category("A我的"), Description("取值范围的最大值，默认 100f"), Browsable(true)]

        public int MaxValue
        {
            get { return _maxValue; }
            set {
                _maxValue = DrawHelper.GetMaxInt(value,MyValue,MinValue);
                if (MyValue> _maxValue)
                {
                    MyValue = _maxValue;
                }
                 Invalidate(); }
        }

        private int _minValue = 0;
        [Category("A我的"), Description("取值范围的最小值，默认 0f"), Browsable(true)]

        public int MinValue
           
        {
            get { return _minValue ; }
            set
            {
                _minValue=DrawHelper.GetMinInt(value,MyValue,MaxValue);
                if (MyValue< _minValue)
                {
                    MyValue = _minValue;
                }
             
                
                Invalidate(); }
        }

        private int _myvalue = 0;
        [Category("A我的"), Description("当前值，默认 0f"), Browsable(true)]

        public int MyValue
        {
            get { return _myvalue; }
            set {
                if (value<MinValue)
                {
                    _myvalue = MinValue;
                    Invalidate();
                    return;

                }
                if (value>MaxValue)
                {
                    _myvalue = MaxValue;
                    Invalidate();
                    return;

                }
                _myvalue = value;
          
                Invalidate();
             


                if (ValueChangeEvent != null)
                {
                    ValueChangeEvent(this, EventArgs.Empty);
                }

            }
        }
        private int _stepAddValue=1;
        [Category("A我的"), Description("美增加或减少一步变化的值，默认 1.0f"), Browsable(true)]
        public int StepAddValue
           
        {
            get { return _stepAddValue; }
            set { _stepAddValue = value; }
        }

        private bool _isFillTrackValue=true;
        [Category("A我的"), Description("是否填充手柄前划过区域，默认 true"), Browsable(true)]
        public bool IsFillTrackValue
        {
            get { return _isFillTrackValue; }
            set { _isFillTrackValue = value; Invalidate(); }


        }

        private bool _isUseTwoColorFillTrackValue = true;
        [Category("A我的"), Description("是否用两种颜色填充手柄前划过区域，默认 true"), Browsable(true)]
        public bool IsUseTwoColorFillTrackValue
        {
            get { return _isUseTwoColorFillTrackValue; }
            set { _isUseTwoColorFillTrackValue = value; Invalidate(); }


        }
        private bool _isFillBarUseTWoColor = true;
        [Category("A我的"), Description("是否填充手柄用两种颜色，默认 true"), Browsable(true)]
        public bool IsillBarUseTWoColor
        {
            get { return _isFillBarUseTWoColor; }
            set { _isFillBarUseTWoColor = value; Invalidate(); }
        }

        private Direction _myDirection=Direction.horizontal;
        [Category("A我的"), Description("控件的方向，默认 水平"), Browsable(true)]
        public Direction MyDirection 
        {
            get { return _myDirection; }
            set { _myDirection = value; Invalidate(); }
        }

        #endregion

        void BeforePain(Graphics myg)
        {

            //MyRect = this.ClientRectangle;
            int Barloction;
             float valueBL;
           //计算需要填充的有值的轨道
                 
                    if (MaxValue > MinValue)
                    {
                        valueBL = Math.Abs(((float)MyValue - MinValue) / (MaxValue - MinValue));
                    }
                    else valueBL = 0;
            //************************
            MyRect = this.ClientRectangle;
            TrackRect.X = MyRect.X;
            TrackRect.Width = MyRect.Width;
            TrackRect.Height = (int)(MyRect.Height / TrackHight);
            TrackRect.Y = MyRect.Y + (int)(MyRect.Height / 2 - TrackRect.Height / 2);




            TrackValueRect.Y = TrackRect.Y;
            TrackValueRect.Height = TrackRect.Height;
            TrackValueRect.Width = (int)(valueBL * TrackRect.Width);
            TrackValueRect.X = 0;



            //计算barRect的所在的当前位置

            BarRect.Height = (int)(MyRect.Height / BarHight);
            BarRect.Width = BarRect.Height;

            BarRect.Y = MyRect.Y + (int)(MyRect.Height / 2 - BarRect.Height / 2);

            //这里修改定位错误
            Barloction = TrackRect.X + (int)(valueBL * (TrackRect.Width - BarRect.Width));

            BarRect.X = Barloction;



            //??*******************************

     

                  
                    


        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            Graphics Myg = e.Graphics;
            Myg.SmoothingMode = SmoothingMode.AntiAlias;
            Myg.CompositingQuality = CompositingQuality.HighQuality;
            Myg.InterpolationMode = InterpolationMode.HighQualityBicubic;
            BeforePain(Myg);

            DrawTrack(Myg, TrackRect);
            if (IsFillTrackValue)
            {
                FillUserValueTrank(Myg, TrackValueRect);
            }
            DrawBar(Myg, BarRect);
            if (IsShowMsg)
            {
                DrawMsg(Myg, BarRect);
            }

        }

        void DrawTrack(Graphics myg,Rectangle trackRect)
        {
         
            
            GraphicsPath trackPath = new GraphicsPath();
            trackPath = DrawHelper.GetTwoHalfCircleRect(trackRect, TrackBorderWidth);

            if (IsUseTrackShadow)
            {

              using (LinearGradientBrush tackFillBrush = new LinearGradientBrush(trackRect, Color.White, Color.White, LinearGradientMode.Vertical))
          
            {
                ColorBlend blend = new ColorBlend();
                blend.Positions = new float[] { 0f,0.25f,0.75f, 1f };
                Color[] colors = new Color[] { TrackShadowColor, TrackFillColor, TrackFillColor, TrackShadowColor };
                blend.Colors = colors;
                tackFillBrush.InterpolationColors = blend;
             
                myg.FillPath(tackFillBrush, trackPath);
            }

            }
            else
            {
                using (SolidBrush trackBrush=new SolidBrush (TrackFillColor))
                {
                    myg.FillPath(trackBrush, trackPath);
                }
            }

            if (IsShowTranckBorder)
            {
                using (Pen trackBorderPen=new Pen(TrackBorderColor,TrackBorderWidth))
                {
                    myg.DrawPath(trackBorderPen, trackPath);
                 
                        

                }

            } }
       
        void FillUserValueTrank(Graphics myg,Rectangle trackValueRect)

        {
            //using (SolidBrush trackValueBrush=new SolidBrush(TrackValueFillColor))
               GraphicsPath path = new GraphicsPath();
                path = DrawHelper.GetTwoHalfCircleRect(trackValueRect, 0);
                if (TrackValueRect.Width < 1)
                {
                    return;
                }

            if (IsUseTwoColorFillTrackValue)
            {

                using (LinearGradientBrush tackValueFillBrush = new LinearGradientBrush(trackValueRect, FilltrackValueFirstColor, FilltrackValueSecondColor, LinearGradientMode.Vertical))

                {

                    myg.FillPath(tackValueFillBrush, path);
                }
            }
            else
            {
                using (SolidBrush trackValueBrush = new SolidBrush(FilltrackValueFirstColor))
                {

                    myg.FillPath(trackValueBrush, path);
                }
            }
            
          
        
        }
            void DrawBar(Graphics myg,Rectangle barRect)
            {
            if (barRect.Right<=TrackRect.Right)
            {

           
            GraphicsPath barPath = new GraphicsPath();
                barPath.AddEllipse(barRect);
                if (_isFillBarUseTWoColor)
                {
                 using (LinearGradientBrush sb = new LinearGradientBrush(BarRect, BarFirstFillColor, BarSecondFillColor, BarAngleFillColor))

                {
                   
                    myg.FillPath(sb, barPath);
                  
                }
                }
                else
                {
                   using (SolidBrush sb=new SolidBrush (BarFirstFillColor))
                    {
                        myg.FillPath(sb, barPath);

                    }
                }
                //
                //using (PathGradientBrush sb = new PathGradientBrush(barPath))
              

                if (IsShowBarBorder&&BarBorderWidth<=BarRect.Height/2)
            {
              using (Pen barBorderPen=new Pen (BarBorderColor,BarBorderWidth))
               {
                     
                        GraphicsPath barBorderPath = DrawHelper.GetCirclePath(barRect, BarBorderWidth );
                  
                        myg.DrawPath(barBorderPen, barBorderPath);
                      
                    }
            }
         
         }

            }

        /// <summary>
        /// 显示值的信息目前显示在 手柄里面
        /// </summary>
        /// <param name="myg"></param>
        /// <param name="msgrect">显示在哪里</param>
       void DrawMsg(Graphics myg,Rectangle msgrect)
        {
            using (SolidBrush fontbrush=new SolidBrush (MsgFontColor))
            {
                StringFormat sf = new StringFormat();
                sf.Alignment = StringAlignment.Center;
                sf.LineAlignment = StringAlignment.Center;

                myg.DrawString(MyValue.ToString(), MsgFont, fontbrush,msgrect,sf );
            }


        }
        int MousePointToMyValue(int PointX)
        {
           
            float sbl =(float) (PointX-TrackRect.X)/TrackRect.Width;
            int NowValue=(int)(sbl* (MaxValue - MinValue) );
            if (NowValue >= MaxValue)
            {
                return MaxValue;
            }
            else if (NowValue <= MinValue)
            {
                return MinValue;
            }
            else return NowValue;
        }
        int OffsetXToMyValue(int OffsetX)
        {
           int OffsetValue =(int)(OffsetX/( TrackValueRect.Width-BarRect.Width) * (MaxValue-MinValue));
                  return  MyValue+ OffsetValue;

        }

        protected override void OnMouseDown(MouseEventArgs e)
        {

            base.OnMouseDown(e);
            if (this.RectangleToScreen(BarRect).Contains(MousePosition) && e.Button == MouseButtons.Left)
            { OldMousePoint = e.Location;
                IsReady= true;
                
              
            }

        }
        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);
     
            if (this.RectangleToScreen(TrackRect).Contains(MousePosition) )
            {
                int uu = e.X - TrackRect.X;
               //此次为优化调节当形状比例不特别协调时候最大值和最小值很难点到
               //     所以牺牲最大和最小值附近部分区域
                if (uu <= (int)BarRect.Width / 4)
                {
                    MyValue = MinValue;
                    return;

                }
                if (uu >= TrackRect.Width - (int)BarRect.Width / 4)
                {
                    MyValue = MaxValue;
                    return;
                }
                MyValue = MousePointToMyValue(uu);


            }
        }
     
        protected override void OnMouseMove(MouseEventArgs e)
        {
          
            //if (this.RectangleToScreen(BarRect).Contains(MousePosition) && e.Button == MouseButtons.Left)
            if (IsReady)
            {
                {
                    //int offsetx = e.X - OldMousePoint.X;
                  
                    OldMousePoint=e.Location;
                    MyValue = MousePointToMyValue(e.X);
                }
            }
       
            base.OnMouseMove(e);
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
          
            IsReady= false;
            base.OnMouseUp(e);

        }
        protected override void OnMouseLeave(EventArgs e)
        {
            IsReady = false;
            base.OnMouseLeave(e);
        }
        private void WHTrackBar_Move(object sender, EventArgs e)
        {
        
        }








        //////////////////////////////////////////////////////////////////////////////////////////////////

    }
}
